using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Reflection;

using GURUCORE.Framework.Core.Data;


namespace GURUCORE.Portal.Core.DataBinding
{
	public class MenuDataSource : HierarchicalDataSourceControl, IHierarchicalDataSource
	{
		internal DTOBase[] m_arrData;
		string m_sPrimaryProperty;
		string m_sReferrenceProperty;

		public MenuDataSource(DTOBase[] p_arrData, string p_sPrimaryProperty, string p_sReferrenceProperty)
		{
			m_arrData = p_arrData;
			m_sPrimaryProperty = p_sPrimaryProperty;
			m_sReferrenceProperty = p_sReferrenceProperty;
		}

		protected override HierarchicalDataSourceView GetHierarchicalView(string viewPath)
		{
			if (viewPath == null || viewPath.Length == 0)
			{
				return new MenuDataSourceView(this, "", m_sPrimaryProperty, m_sReferrenceProperty);
			}
			return new MenuDataSourceView(this, viewPath, m_sPrimaryProperty, m_sReferrenceProperty);
		}

		event EventHandler DataSourceChanged
		{
			add
			{
				this.DataSourceChanged += value;
			}
			remove
			{
				this.DataSourceChanged -= value;
			}
		}
	}

	internal class MenuDataSourceView : HierarchicalDataSourceView
	{
		private MenuDataSource _owner;
		private string _viewPath;
		private string m_sPrimaryProperty;
		private string m_sReferrenceProperty;

		internal MenuDataSourceView(MenuDataSource owner, string viewPath, string p_sPrimaryProperty, string p_sReferrenceProperty)
		{
			_owner = owner;
			_viewPath = (viewPath == null) ? String.Empty : viewPath;

			m_sPrimaryProperty = p_sPrimaryProperty;
			m_sReferrenceProperty = p_sReferrenceProperty;
		}

		public override IHierarchicalEnumerable Select()
		{
			List<DTOBase> arrData = new List<DTOBase>(this._owner.m_arrData);

            List<DTOBase> arrView = arrData.FindAll(
                delegate(DTOBase dtoMatch)
                {
                    if (dtoMatch.DTOTag == null && string.IsNullOrEmpty(_viewPath))
                    {
                        return true;
                    }
                    else if (dtoMatch.DTOTag != null)
                    {
                        return dtoMatch.DTOTag.ToString() == _viewPath;
                    }
                    else
                    {
                        return false;
                    }
                }
                );

			return new MenuHierarchicalEnumerable(arrView.ToArray(), _owner, m_sPrimaryProperty, m_sReferrenceProperty);
		}
	}

	internal class MenuHierarchicalEnumerable : IHierarchicalEnumerable
	{
		DTOBase[] _rows;
		MenuDataSource _owner;
		string m_sPrimaryProperty;
		string m_sReferrenceProperty;

		internal MenuHierarchicalEnumerable(DTOBase[] rows, MenuDataSource owner, string p_sPrimaryProperty, string p_sReferrenceProperty)
		{
			_rows = rows;
			_owner = owner;

			m_sPrimaryProperty = p_sPrimaryProperty;
			m_sReferrenceProperty = p_sReferrenceProperty;
		}

		#region IHierarchicalEnumerable Members

		IHierarchyData IHierarchicalEnumerable.GetHierarchyData(object enumeratedItem)
		{
			return (IHierarchyData)enumeratedItem;
		}

		#endregion

		#region IEnumerable Members

		System.Collections.IEnumerator IEnumerable.GetEnumerator()
		{
			foreach (DTOBase row in _rows)
			{
				yield return new MenuHierarchyData(row, _owner, m_sPrimaryProperty, m_sReferrenceProperty);
			}
		}

		#endregion
	}

	internal class MenuHierarchyData : IHierarchyData
	{
		private DTOBase m_dtoData;
		MenuDataSource _owner;
		PropertyInfo m_oPrimaryProperty;
		PropertyInfo m_oReferrenceProperty;

		internal MenuHierarchyData(DTOBase p_dtoData, MenuDataSource owner, string p_sPrimaryProperty, string p_sReferrenceProperty)
		{
			m_dtoData = p_dtoData;
			_owner = owner;

			Type tDTOType = p_dtoData.GetType();
			m_oPrimaryProperty = tDTOType.GetProperty(p_sPrimaryProperty);
			m_oReferrenceProperty = tDTOType.GetProperty(p_sReferrenceProperty);
		}

		IHierarchicalEnumerable IHierarchyData.GetChildren()
		{
			List<DTOBase> arrData = new List<DTOBase>(this._owner.m_arrData);

			List<DTOBase> arrView = arrData.FindAll(delegate(DTOBase dtoMatch)
				{
					object oPrimaryValue = m_oPrimaryProperty.GetValue(m_dtoData, null);
					object oReferrenceValue = m_oReferrenceProperty.GetValue(dtoMatch, null);
					return oPrimaryValue.Equals(oReferrenceValue);
				});

			if (arrView.Count > 0)
			{
				return new MenuHierarchicalEnumerable(arrView.ToArray(), _owner, m_oPrimaryProperty.Name, m_oReferrenceProperty.Name);
			}
			else
			{
				return null;
			}
		}

		IHierarchyData IHierarchyData.GetParent()
		{
			List<DTOBase> arrData = new List<DTOBase>(this._owner.m_arrData);

			DTOBase dtoView = arrData.Find(delegate(DTOBase dtoMatch)
				{
					object oPrimaryValue = m_oPrimaryProperty.GetValue(dtoMatch, null);
					object oReferrenceValue = m_oReferrenceProperty.GetValue(m_dtoData, null);
					return oPrimaryValue.Equals(oReferrenceValue);
				});

			if (dtoView != null)
			{
				return new MenuHierarchyData(dtoView, _owner, m_oPrimaryProperty.Name, m_oReferrenceProperty.Name);
			}
			else
			{
				return null;
			}
		}

		bool IHierarchyData.HasChildren
		{
			get
			{
				List<DTOBase> arrData = new List<DTOBase>(this._owner.m_arrData);

				List<DTOBase> arrView = arrData.FindAll(delegate(DTOBase dtoMatch)
					{
						object oPrimaryValue = m_oPrimaryProperty.GetValue(m_dtoData, null);
						object oReferrenceValue = m_oReferrenceProperty.GetValue(dtoMatch, null);
						return oPrimaryValue.Equals(oReferrenceValue);
					});

				if (arrView.Count > 0)
				{
					return true;
				}
				else
				{
					return false;
				}
			}
		}

		object IHierarchyData.Item
		{
			get
			{
				return m_dtoData;
			}
		}

		string IHierarchyData.Path
		{
			get
			{
                return null == m_dtoData.DTOTag ? string.Empty : m_dtoData.DTOTag.ToString();
			}
		}

		string IHierarchyData.Type
		{
			get
			{
				if (m_dtoData == null)
				{
					return string.Empty;
				}
				else
				{
					return "DTOBase";
				}
			}
		}
	}
}
